class Depend {
	constructor() {
		// this.reactiveFns = []
		this.reactiveFns = new Set()
	}

	addDepend(fn) {
		if (fn) {
			this.reactiveFns.add(fn)
		}
	}

	depend() {
		if (reactiveFn) {
			this.reactiveFns.add(reactiveFn)
		}
	}

	notify() {
		this.reactiveFns.forEach((fn) => fn())
	}
}

// 法案1： Object.defineProperty() -> vue2
function reactive(obj) {
	const objProxy = new Proxy(obj, {
		set: function (target, key, newValue, receiver) {
			// receiver: Proxy 或者继承 Proxy 的对象
			// target[key] = newValue
			Reflect.set(target, key, newValue, receiver)
			const dep = getDepend(target, key)
			dep.notify()
		},
		get: function (target, key, receiver) {
			const dep = getDepend(target, key)
			dep.depend()
			return Reflect.get(target, key, receiver)
		},
	})

	return objProxy
}

// 封装一个函数：负责通过obj的key获取对应的Depend对象
const objMap = new WeakMap()
function getDepend(obj, key) {
	// 根据obj对象找到map对象
	let map = objMap.get(obj)
	if (!map) {
		map = new Map()
		objMap.set(obj, map)
	}

	// 2. 根据key，找到对应的depend对象
	let dep = map.get(key)
	if (!dep) {
		dep = new Depend()
		map.set(key, dep)
	}

	return dep
}

let reactiveFn = null
function watchFn(fn) {
	reactiveFn = fn
	fn()
	reactiveFn = null
}

// ============== 业务代码 ==============
const obj = reactive({
	name: 'why',
	age: 28,
	adress: '广州市',
})

watchFn(function () {
	console.log('1.foo:', obj.name)
	console.log('2.foo:', obj.age)
})

watchFn(function () {
	console.log('3.foo:', obj.adress)
})

watchFn(function () {
	console.log('4.foo:', obj.age)
	console.log('5.foo:', obj.adress)
})

// 修改obj的属性
console.log('name属性改变')
obj.name = 'kobe'

const user = reactive({
	nickname: 'abc',
	level: 100,
})

watchFn(function () {
	console.log('nickname:', user.nickname)
	console.log('level:', user.level)
})

console.log('user的操作')
user.nickname = '张三'
